package com.atguigu.gulimall.auth.controller;


import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.constant.AuthServiceConstant;
import com.atguigu.common.exception.BizCodeEnum;
import com.atguigu.common.utils.R;
import com.atguigu.common.vo.MemberOAuthVo;
import com.atguigu.gulimall.auth.feign.MemberFeignService;
import com.atguigu.gulimall.auth.feign.ThirdPartyFeignService;
import com.atguigu.gulimall.auth.vo.UserLoginVo;
import com.atguigu.gulimall.auth.vo.UserRegistVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * （1）通过form表单提交访问首页
 */
@Controller
public class LoginController {

    @Autowired
    MemberFeignService memberFeignService;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    ThirdPartyFeignService feignService;

    /**
     *  点击发送验证码
     */
    @ResponseBody//thymeleaf异常,无法解析模版数据，
    @GetMapping("/sms/sendcode")
    public R sendCode(@RequestParam("phone") String phone){
        //如果时间<60秒就稍后再试
        String redisCode = redisTemplate.opsForValue().get(AuthServiceConstant.SMS_CODE_CACAHE_PRIFIX + phone);
        if (!StringUtils.isEmpty(redisCode)){
            Long time = Long.parseLong(redisCode.split("_")[1]);
            if ((System.currentTimeMillis() - time) < 60000){
                return R.error(BizCodeEnum.SMSCODE_EXCEPTIPN.getCode(),BizCodeEnum.SMSCODE_EXCEPTIPN.getMsg());
            }
        }
        //存redis key-phone,value-code，过期时间：10分钟
        //String code = UUID.randomUUID().toString().substring(0, 5);
        String code = strCode();
        String redisVal = code + "_" + System.currentTimeMillis();

        redisTemplate.opsForValue().set(AuthServiceConstant.SMS_CODE_CACAHE_PRIFIX+phone,redisVal,10, TimeUnit.MINUTES);
        feignService.sms(phone,code);

        return R.ok();
    }

    //TODO 重定向携带数据将数据存入Session ——> 分布式Session不共享问题？
    @PostMapping("/regist")//点击立即注册发送请求
    public String regist(@Valid UserRegistVo vo, BindingResult result, RedirectAttributes redirectAttributes){
        //如果校验不通过，刷新页面，展示错误信息
        if(result.hasErrors()) {
            //1.取出校验失败结果，存入map
            Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
            //2.向请求域传值
            redirectAttributes.addFlashAttribute("errors", errors);
            //3.校验出现错误——>重定向页面到注册页
            return "redirect:http://auth.gulimall.com/reg.html";
        }
        //校验通过
        //1111_15171284192
        String redisVal = redisTemplate.opsForValue().get(AuthServiceConstant.SMS_CODE_CACAHE_PRIFIX + vo.getPhone());
        if (!StringUtils.isEmpty(redisVal)){
            String phone = redisVal.split("_")[0];
            if (vo.getCode().equals(phone)){
                //验证码通过，调用member服务注册会员
                R r = memberFeignService.regist(vo);
                if (r.getCode() == 0){
                    //用户注册成功，跳转到登陆页
                    return "redirect:http://auth.gulimall.com/login.html";
                }else {
                    //用户注册失败，用户名已存在或手机号已存在
                    Map<String, String> map = new HashMap<>();
                    String msg = (String)r.getMsg(new TypeReference<String>() {});
                    if (r.getCode().equals(BizCodeEnum.USERNAME_EXIST_EXCEPTION.getCode())){
                        map.put("userName",msg);
                    }
                    if (r.getCode().equals(BizCodeEnum.PHONE_EXIST_EXCEPTION.getCode())){
                        map.put("phone",msg);
                    }
                    redirectAttributes.addFlashAttribute("errors",map);
                    return "redirect:http://auth.gulimall.com/reg.html";
                }
            }else {
                //验证码不正确
                Map<String, String> map = new HashMap<>();
                map.put("code","验证码不正确");
                redirectAttributes.addFlashAttribute("errors",map);
                return "redirect:http://auth.gulimall.com/reg.html";
            }
        }else {
            //验证码不存在，已失效
            Map<String, String> map = new HashMap<>();
            map.put("code","验证码已失效");
            redirectAttributes.addFlashAttribute("errors",map);
            return "redirect:http://auth.gulimall.com/reg.html";
        }

    }


    public String strCode(){
        Random random = new Random();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 4; i++) {
            int nextInt = random.nextInt(10);
            stringBuilder.append(nextInt);
        }
        return stringBuilder.toString();

    }


    /**
     * 登录成功再次访问登录页则直接跳转首页
     */
    @GetMapping("/login.html")
    public String login(HttpSession httpSession){
        //如果查询不为空，代表登录过，直接跳转首页
        //如果查询为空则未登陆过，则访问登录页
        Object attribute = httpSession.getAttribute(AuthServiceConstant.LOGIN_USER);
        if (attribute != null){
            return "redirect:http://gulimall.com";
        }else {
            //进入登录页login.html，这里不是直接访问下面的/login请求，而是在login.html中进行form表单提交 访问下面的/login
            return "login";
        }

    }

    /**
     * http://auth.gulimall.com/login
     */
    @PostMapping("/login")
    public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession httpSession){

        //校验用户名密码
        R<MemberOAuthVo> r = memberFeignService.login(vo);
        if (r.getCode() == 0){
            //往session存入用户信息
            MemberOAuthVo data = r.getData(new TypeReference<MemberOAuthVo>() {});
            httpSession.setAttribute(AuthServiceConstant.LOGIN_USER,data);
            return "redirect:http://gulimall.com";
        }else {
            String msg = (String) r.getMsg(new TypeReference<String>() {});
            Map<String, String> errors = new HashMap<>();
            errors.put("msg", msg);
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }

    }



}
